﻿using System.Drawing;
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Imaging;

namespace ImageProcessing.Utility
{
    public class ImageExt : IDisposable
    {
        public ImageExt()
        {
        }

        public static ImageExt Load(Image image){
            return new ImageExt(image);
        }

        private Image _image;
        public Image ImageFile
        {
            get { return _image; }
            set
            {
                _image = value;
            }
        }

        public ImageExt(Image image)
        {
            ImageFile = image;
        }
        public int Width
        {
            get { return _image.Width; }
        }
        public int Height
        {
            get { return ImageFile.Height; }
        }

        public Image ToImage()
        {
            return _image;
        }

        public string CameraModel { get { return GetCameraModel(); } }

        public ImageExt CropCenter(int ratioX, int ratioY)
        {
            ImageExt image = new ImageExt();

            int targetHeight = Width / ratioX * ratioY;
            if (targetHeight > Height)
            {
                int targetWidth = Height / ratioY * ratioX;
                targetHeight = Height;
                int startX = (Width - targetWidth) / 2;
                int startY = 0;

                Bitmap target = new Bitmap(targetWidth, targetHeight);
                using (Graphics g = Graphics.FromImage(target))
                {
                    g.DrawImage(ImageFile, new Rectangle(0, 0, targetWidth, targetHeight), startX, startY, targetWidth, targetHeight, GraphicsUnit.Pixel);

                }
                image.ImageFile = target;
            }
            else if (targetHeight < Height)
            {
                int targetWidth = Width;
                int startX = 0;
                int startY = (Height - targetHeight) / 2;

                Bitmap target = new Bitmap(targetWidth, targetHeight);
                using (Graphics g = Graphics.FromImage(target))
                {
                    g.DrawImage(ImageFile, new Rectangle(0, 0, targetWidth, targetHeight), startX, startY, targetWidth, targetHeight, GraphicsUnit.Pixel);

                }
                image.ImageFile = target;
            }
            else
                image.ImageFile = ImageFile;
            return image;
        }

        public ImageExt Crop(int ratioX, int ratioY)
        {
            ImageExt image = new ImageExt();
            int targetHeight = Width / ratioX * ratioY;
            if (targetHeight > Height)
            {
                int targetWidth = Height / ratioY * ratioX;
                targetHeight = Height;

                Bitmap target = new Bitmap(targetWidth, targetHeight);
                using (Graphics g = Graphics.FromImage(target))
                {
                    g.DrawImage(ImageFile, new Rectangle(0, 0, targetWidth, targetHeight), 0, 0, targetWidth, targetHeight, GraphicsUnit.Pixel);

                }
                image.ImageFile = target;
            }
            else if (targetHeight < Height)
            {
                int targetWidth = Width;

                Bitmap target = new Bitmap(targetWidth, targetHeight);
                using (Graphics g = Graphics.FromImage(target))
                {
                    g.DrawImage(ImageFile, new Rectangle(0, 0, targetWidth, targetHeight), 0, 0, targetWidth, targetHeight, GraphicsUnit.Pixel);

                }
                image.ImageFile = target;
            }
            else
                image.ImageFile = ImageFile;
            return image;
        }

        public ImageExt Resize(Size size)
        {
            ImageExt image = new ImageExt();
            Bitmap target = new Bitmap(size.Width, size.Height);
            using (Graphics g = Graphics.FromImage(target))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(ImageFile, 0, 0, size.Width, size.Height);
            }
            image.ImageFile = target;
            return image;
        }

        public ImageExt Resize(int ratioX, int ratioY, int resizedWidth)
        {

            int resizedHeight = resizedWidth / ratioX * ratioY;

            return CropCenter(ratioX, ratioY).Resize(new Size(resizedWidth, resizedHeight));

        }
        public ImageExt Watermark(Image watermark, WaterMarkPosition position)
        {
            return Watermark(watermark, position, 0);
        }
        public ImageExt Watermark(Image watermark, WaterMarkPosition position, int margin)
        {
            int waterMarkX = watermark.Width;
            int waterMarkY = watermark.Height;
            if (position == WaterMarkPosition.TOPLEFT)
            {
                return Watermark(watermark, margin, margin);
            }
            else if (position == WaterMarkPosition.TOPRIGHT)
            {
                return Watermark(watermark, Width - waterMarkX - margin, margin);
            }
            else if (position == WaterMarkPosition.TOPCENTER)
            {
                return Watermark(watermark, (Width - waterMarkX) / 2, margin);
            }
            else if (position == WaterMarkPosition.BOTTOMCENTER)
            {
                return Watermark(watermark, (Width - waterMarkX) / 2, Height - waterMarkY - margin);
            }
            else if (position == WaterMarkPosition.BOTTOMLEFT)
            {
                return Watermark(watermark, margin, Height - waterMarkY - margin);
            }
            else if (position == WaterMarkPosition.BOTTOMRIGHT)
            {
                return Watermark(watermark, Width - waterMarkX - margin, Height - waterMarkY - margin);
            }
            else if (position == WaterMarkPosition.MIDDLELEFT)
            {
                return Watermark(watermark, margin, (Height - waterMarkY) / 2);
            }
            else if (position == WaterMarkPosition.MIDDLERIGHT)
            {
                return Watermark(watermark, Width - waterMarkX - margin, (Height - waterMarkY) / 2);
            }
            else if (position == WaterMarkPosition.CENTER)
            {
                return Watermark(watermark, (Width - waterMarkX) / 2, (Height - waterMarkY) / 2);
            }
            return null;
        }

        public ImageExt Watermark(Image watermark, int xPosition, int yPosition)
        {
            Image img = ImageFile.Clone() as Image;
            Bitmap transparentLogo = new Bitmap(watermark.Width, watermark.Height);
            using (Graphics g = Graphics.FromImage(img))
            {
                using (Graphics wg = Graphics.FromImage(transparentLogo))
                {
                    ColorMatrix matrix = new ColorMatrix();
                    matrix.Matrix33 = 0.5F;
                    ImageAttributes attributes = new ImageAttributes();
                    attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
                    wg.DrawImage(watermark, new Rectangle(0, 0, watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel, attributes);
                }
                g.DrawImage(watermark, xPosition, yPosition);
            }
            return new ImageExt(img);
        }

        public void SaveJpeg(string path)
        {
            long quality = 50;
            SaveJpeg(path, quality);
        }

        public void SaveJpeg(string path, long quality)
        {
            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
            if (jpegCodec == null)
                return;
            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            ImageFile.Save(path, jpegCodec, encoderParams);
        }

        private ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

            for (int i = 0; i < codecs.Length; i++)
            {
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            }
            return null;
        }

        private string GetCameraModel()
        {
            PropertyItem[] propItems = ImageFile.PropertyItems;
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            PropertyItem cameraType = null;
            foreach (PropertyItem item in propItems)
            {
                if (item.Id == 272)
                {
                    cameraType = item;
                    break;
                }
            } //get camera type from Exif metadata
            if (cameraType != null)
            {
                return encoding.GetString(cameraType.Value);
            }
            return string.Empty;
        }



        public void Dispose()
        {
            _image.Dispose();
        }
    }
    public enum WaterMarkPosition
    {
        TOPLEFT,
        TOPRIGHT,
        TOPCENTER,
        BOTTOMLEFT,
        BOTTOMRIGHT,
        BOTTOMCENTER,
        MIDDLELEFT,
        MIDDLERIGHT,
        CENTER
    }
}